﻿using Basic.FlowApplication.Extend;
using Basic.FlowApplication.Interface;
using Basic.FlowApplication.Model;
using Basic.FlowApplication.Model.AuditLog;
using Basic.FlowCollect;
using Basic.FlowModel;
using Basic.FlowModel.AuditState;
using Basic.FlowRemoteModel;
using Basic.FlowRemoteModel.Application.Model;
using WeDonekRpc.Client.Attr;
using WeDonekRpc.Helper;

namespace Basic.FlowApplication.AuditEvent
{
    [IocName("Audit_5")]
    [ClassLifetimeAttr(ClassLifetimeType.Scope)]
    internal class WithdrawAuditEvent : IItemAuditEvent
    {
        private readonly IFlowAuditCopyLogCollect _CopyMsg;
        private readonly IFlowAuditNodeStateCollect _NodeState;
        public WithdrawAuditEvent ( IFlowAuditCopyLogCollect copy,
            IFlowAuditNodeStateCollect nodeState )
        {
            this._NodeState = nodeState;
            this._CopyMsg = copy;
        }
        public AfootAuditLogItem ItemAudit ( Model.AuditFlowBody flow, FlowAuditLogState log, AuditRes result )
        {
            AfootAuditLogItem item = log.LogItem.Find(a => a.Id == result.ItemId);
            item.CheckAuditItem(result, ConstDic.AllowWithdraw);

            item.AuditState = FlowAuditItemStatus.已撤回;
            item.SignFileId = result.SignFileId;
            log.ToVoidItem(flow, item.NodeId, item.Id);
            FlowNode node = flow.Nodes[item.NodeId];
            log.LogItem.Add(new AfootAuditLogItem
            {
                CompanyId = item.CompanyId,
                EmpByDeptId = item.EmpByDeptId,
                EmpByUnitId = item.EmpByUnitId,
                BatchNo = item.BatchNo,
                EmpId = item.EmpId,
                NextDeptId = item.NextDeptId,
                RootBatchNo = item.NodeType == FlowNodeType.子流程 ? 0 : item.RootBatchNo,
                RootNodeId = item.RootNodeId,
                AuditOpinion = item.AuditOpinion,
                NodeId = item.NodeId,
                NodeType = item.NodeType,
                PrevBackNo = item.PrevBackNo,
                PrevNodeId = item.PrevNodeId,
                PrtBatchNo = item.PrtBatchNo,
                OptItemId = item.OptItemId,
                MarkState = item.MarkState,
                TimeOut = node.LimitTime.HasValue ? DateTime.Now.AddMinutes(node.LimitTime.Value) : null
            });
            this._Restore(flow, log, item);
            return item;
        }
        private void _Restore ( AuditFlowBody flow, FlowAuditLogState log, AfootAuditLogItem item )
        {
            List<AfootAuditLogItem> list = log.LogItem.FindAll(c => c.OptItemId == item.Id && c.Status == FlowAuditItemStatus.已作废 && c.ChangeType == LogItemChangeType.None);
            if ( list.Count > 0 )
            {
                long[] ids = list.Convert(a => a.AuditState == FlowAuditItemStatus.审核进行中 || a.AuditState == FlowAuditItemStatus.待开始, a => a.Id);
                Dictionary<long, long[]> copyEmp = this._CopyMsg.GetToEmpId(ids, FlowMsgType.审核通过);
                list.ForEach(c =>
                {
                    if ( c.AuditState == FlowAuditItemStatus.审核通过 && c.SubFlowState == FlowSubAuditStatus.已作废 )
                    {
                        AfootAuditLogItem set = c.Copy();
                        set.SubFlowState = FlowSubAuditStatus.审核进行中;
                        log.LogItem.Add(set);
                    }
                    else if ( c.Status == FlowAuditItemStatus.已作废 )
                    {
                        FlowNode cur = flow.Nodes[c.NodeId];
                        AfootAuditLogItem set = c.Copy();
                        set.OptItemId = item.Id;
                        set.CopyId = copyEmp.GetValueOrDefault(c.Id);
                        set.TimeOut = cur.LimitTime.HasValue ? DateTime.Now.AddMinutes(cur.LimitTime.Value) : null;
                        log.LogItem.Add(set);
                    }
                });
            }
            RestoreNodeState[] state = this._NodeState.GetRestoreNode(log.Id, item.Id);
            if ( !state.IsNull() )
            {
                state.ForEach(c =>
                {
                    log.SetNodeState(c.NodeId, c.PrevStatus.Value, item.Id);
                });
            }
        }
    }
}